/**
* Copyright 2013 Netflix, Inc.
* <p/>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.servo.tag.aws;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.autoscaling.AmazonAutoScaling;
import com.amazonaws.services.autoscaling.model.AutoScalingInstanceDetails;
import com.amazonaws.services.autoscaling.model.DescribeAutoScalingInstancesRequest;
import com.netflix.servo.aws.AwsPropertyKeys;
import com.netflix.servo.aws.AwsServiceClients;
import com.netflix.servo.aws.constants.Dimensions;
import com.netflix.servo.tag.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.List;
/**
* Group of Tags who's values will be dynamically set at runtime
* based on amazon api calls.
* <p/>
* The keys for and values of these Tags are consistent with AWS naming.
*/
public enum AwsInjectableTag implements Tag {
AUTOSCALE_GROUP(Dimensions.AUTOSCALING_GROUP.getAwsString(), getAutoScaleGroup()),
INSTANCE_ID(Dimensions.INSTANCE_ID.getAwsString(), getInstanceId()),
AVAILABILITY_ZONE(Dimensions.AVAILABILITY_ZONE.getAwsString(), getZone()),
AMI_ID(Dimensions.AMI_IMAGE_ID.getAwsString(), getAmiId()),
INSTANCE_TYPE(Dimensions.INSTANCE_TYPE.getAwsString(), getInstanceType()),
LOCAL_HOSTNAME("local-hostname", getLocalHostname()),
LOCAL_IPV4("local-ipv4", getLocalIpv4()),
PUBLIC_HOSTNAME("public-hostname", getPublicHostname()),
PUBLIC_IPV4("public-ipv4", getPublicIpv4());
private static final String METADATA_URL = "http://instance-data/latest/meta-data";
private static final String UNDEFINED = "undefined";
private static Logger getLogger() {
return LoggerFactory.getLogger(AwsInjectableTag.class);
}
private final String key;
private final String value;
AwsInjectableTag(String key, String val) {
this.key = key;
this.value = val;
}
/**
* @return Amazon compliant string representation of the key.
*/
public String getKey() {
return key;
}
/**
* @return value as determined at runtime for the key.
*/
public String getValue() {
return value;
}
public String tagString() {
return key + "=" + value;
}
static String getAutoScaleGroup() {
try {
String credFileProperty = System.getProperties().getProperty(
AwsPropertyKeys.AWS_CREDENTIALS_FILE.getBundle());
AWSCredentials credentials;
if (credFileProperty != null) {
credentials = new PropertiesCredentials(new File(credFileProperty));
} else {
credentials = new DefaultAWSCredentialsProviderChain().getCredentials();
}
AmazonAutoScaling autoScalingClient = AwsServiceClients.autoScaling(credentials);
List<AutoScalingInstanceDetails> autoScalingInstances = autoScalingClient.describeAutoScalingInstances(
new DescribeAutoScalingInstancesRequest().withInstanceIds(getInstanceId())).getAutoScalingInstances();
return autoScalingInstances.isEmpty() ? UNDEFINED : autoScalingInstances.get(0).getAutoScalingGroupName();
} catch (Exception e) {
getLogger().error("Unable to get ASG name.", e);
return UNDEFINED;
}
}
static String getInstanceId() {
return getUrlValue("/instance-id");
}
@SuppressWarnings("PMD")
static String getUrlValue(String path) {
BufferedReader reader = null;
try {
URL url = new URL(METADATA_URL + path);
reader = new BufferedReader(new InputStreamReader(url.openStream(),
Charset.forName("UTF-8")));
return reader.readLine();
} catch (Exception e) {
getLogger().warn("Unable to read value from AWS metadata URL", e);
return UNDEFINED;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
getLogger().info("Ignoring failure while closing the stream", e);
}
}
}
static String getZone() {
return getUrlValue("/placement/availability-zone");
}
static String getAmiId() {
return getUrlValue("/ami-id");
}
static String getInstanceType() {
return getUrlValue("/instance-type");
}
static String getLocalHostname() {
return getUrlValue("/local-hostname");
}
static String getLocalIpv4() {
return getUrlValue("/local-ipv4");
}
static String getPublicHostname() {
return getUrlValue("/public-hostname");
}
static String getPublicIpv4() {
return getUrlValue("/public-ipv4");
}
}